String.prototype.startWith=function(str){
if(str==null||str==""||this.length==0||str.length>this.length)
  return false;
if(this.substr(0,str.length)==str)
  return true;
else
  return false;
return true;
}

String.prototype.endWith=function(str){
	if(str==null||str==""||this.length==0||str.length>this.length)
	  return false;
	if(this.substring(this.length-str.length)==str)
	  return true;
	else
	  return false;
	return true;
}

/**
* 获取jquery 的outerHtml
* from   http://www.isharey.com/?p=1205
* @param $dom jquery对象
* @return  string
*/
$.extend({
	"getJqueryOuterHtml": function ($dom) {
		   return $($('<div></div>').html($dom.clone())).html();
		}
});

$.fn.serializeJson=function(){
	var serializeObj={};
	var array=this.serializeArray();
	var str=this.serialize();
	$(array).each(function(){
	if(serializeObj[this.name]){
	if($.isArray(serializeObj[this.name])){
	serializeObj[this.name].push(this.value);
	}else{
	serializeObj[this.name]=[serializeObj[this.name],this.value];
	}
	}else{
	serializeObj[this.name]=this.value;
	}
	});
	return serializeObj;
	};


$(document).ready(function(){

	//highlight current / active link
	$('ul.main-menu li a').each(function(){
		if(String(window.location).startWith($($(this))[0].href))
			$(this).parent().addClass('active');
	});


	//other things to do on document ready, seperated for ajax calls
	docReady();
});

function docReady(){
	$.extend({"appCtx":$("#app-ctx").attr('href')});

	//art template
	template.openTag = '<@';
	template.closeTag = '@>';

	//prevent # links from moving to top
	$('a[href="#"][data-top!=true]').click(function(e){
		e.preventDefault();
	});

	//rich text editor
	$('.cleditor').cleditor();

	//datepicker
	$('.datepicker').datepicker();
	$('.datepicker-dropdown-year-month').each(function(i,e){
		$(e).datepicker({changeYear:true,changeMonth:true,yearRange:$(e).attr('yearRange')});
	});
	$.datepicker.setDefaults($.datepicker.regional['zh-CN']);

	//notifications
	$('.noty').click(function(e){
		e.preventDefault();
		var options = $.parseJSON($(this).attr('data-noty-options'));
		noty(options);
	});

	// table
	$("table .check-all").live('click',function(e){
		var cbs = $(e.target).closest('table').find('tbody input[type=checkbox]');
		cbs.attr('checked',$(e.target).attr('checked')?true:false).trigger('change');
		$.uniform.update(cbs);
	});

	//form
	// validation engine 默认配置更改
	$.validationEngine.defaults.promptPosition="centerRight";	// 位置：右侧
	$.validationEngine.defaults.scroll=false;	// scroll在modal中验证时有bug
	$.validationEngine.defaults.maxErrorsPerField=1;	// 只显示一个error msg
	$.validationEngine.defaults.onValidationComplete=function(form,status,beforeSubmit){	//disable掉按钮防止表单重复提交，添加了一个参数，详见validationEngne源码
		if(status == true && beforeSubmit){
			form.find("*[type=submit]").attr('disabled',true).text("提交中...");
			return true;
		}
		return false;
	};

	$("form button[type=reset]").live('click',function(e){	//清空
		e.preventDefault();
		$(e.target).closest('form').find(":input").each(function() {
			var type = this.type;
		    var tag = this.tagName.toLowerCase(); // normalize case
		    // it's ok to reset the value attr of text inputs,
		    // password inputs, and textareas
		    if (type == 'text' || type == 'password' || tag == 'textarea' || type=="file")
		      this.value = "";

		    /*
		     	不清空checkbox、radio、select
		    // checkboxes and radios need to have their checked state cleared
		    // but should *not* have their 'value' changed
		    else if (type == 'checkbox' || type == 'radio')
		      this.checked = false;
		    // select elements need to have their 'selectedIndex' property set to -1
		    // (this works for both single and multiple select elements)
		    //else if (tag == 'select')
		      this.selectedIndex = -1;

		      */
		    $.uniform.update(this);	//更新uniform样式
		    $(this).validationEngine('hide'); //隐藏VE的tip
		});
		// file upload
		$(e.target).closest('form').find('*[data-dismiss=fileupload]').click();
	});

	// 二级学科、科室、病区、教授组、老师联动下拉框
	var emptyOption = $('<option value=""></option>');

	$("select.select-ss").live("change",function(){
		var dept = $(this).closest('form').find('select.select-dept');
		if(dept.length == 0)	return;
		dept.validationEngine('hide');	// 隐藏VE的tip，不然会错位

		var isDeptRequired = dept.is('.required');
		var val = $(this).val();

		// 清空科室下拉框，如果不是必填的，塞一个空的选项进去
		dept.html('');
		if(!isDeptRequired) dept.prepend(emptyOption.clone());
		//二级学科选择了空值，则让科室选择第一个选项(空)，并手动触发select事件，返回
		if(!val){
			dept.selectedIndex = 0;
			$.uniform.update(dept);
			dept.trigger("change");
		}else{
			$.get($.appCtx+ "/data-manage/department/all/"+val,function(data) {
				var initIndex = 0;	// 初始要选中哪个选项
				if(data){
					var initVal = dept.attr("init-value");
					$(data).each(function(i,e){
						dept.append($('<option value="'+e.id+'">'+e.name+'</option>'))
						if(initVal != undefined && initVal == e.id)
							initIndex = i+(isDeptRequired?0:1);//非必填的科室选择框要多一个空选择项
					});
				}
				dept.find('option').eq(initIndex).attr('selected',true);
				$.uniform.update(dept);
				dept.removeAttr('init-value').trigger("change");
			});
		}
	});

	$("select.select-dept").live("change",function(){
		var area = $(this).closest('form').find('select.select-area');
		if(area.length == 0)	return;
		area.validationEngine('hide');	// 隐藏VE的tip，不然会错位

		var isAreaRequired = area.is('.required');
		var val = $(this).val();

		// 清空病区下拉框，如果不是必填的，塞一个空的选项进去
		area.html('');
		if(!isAreaRequired) area.prepend(emptyOption.clone());
		//科室选择了空值，则让病区选择第一个选项(空)，并手动触发select事件，返回
		if(!val){
			area.selectedIndex = 0;
			$.uniform.update(area);
			area.trigger("change");
		}else{
			$.get($.appCtx+ "/data-manage/area/all/"+val,function(data) {
				var initIndex = 0;	// 初始要选中哪个选项
				if(data){
					var initVal = area.attr("init-value");
					$(data).each(function(i,e){
						area.append($('<option value="'+e.id+'">'+e.name+'</option>'))
						if(initVal != undefined && initVal == e.id)
							initIndex = i+(isAreaRequired?0:1);//非必填的科室选择框要多一个空选择项
					});
				}
				area.find('option').eq(initIndex).attr('selected',true);
				$.uniform.update(area);
				area.removeAttr('init-value').trigger("change");
			});
		}
	});

	$("select.select-area").live("change",function(){
		var team = $(this).closest('form').find('select.select-team');
		if(team.length == 0)	return;
		team.validationEngine('hide');	// 隐藏VE的tip，不然会错位

		var isTeamRequired = team.is('.required');
		var val = $(this).val();

		// 清空教授组下拉框，如果不是必填的，塞一个空的选项进去
		team.html('');
		if(!isTeamRequired) team.prepend(emptyOption.clone());
		//病区选择了空值，则让教授组选择第一个选项(空)，并手动触发select事件，返回
		if(!val){
			team.selectedIndex = 0;
			$.uniform.update(team);
			team.trigger("change");
		}else{
			$.get($.appCtx+ "/data-manage/teacher-team/all/"+val,function(data) {
				var initIndex = 0;	// 初始要选中哪个选项
				if(data){
					var initVal = team.attr("init-value");
					$(data).each(function(i,e){
						team.append($('<option value="'+e.id+'">'+e.name+'</option>'))
						if(initVal != undefined && initVal == e.id)
							initIndex = i+(isTeamRequired?0:1);//非必填的科室选择框要多一个空选择项
					});
				}
				team.find('option').eq(initIndex).attr('selected',true);
				$.uniform.update(team);
				team.removeAttr('init-value').trigger("change");
			});
		}
	});

	$("select.select-team").live("change",function(){
		var teacher = $(this).closest('form').find('select.select-teacher');
		if(teacher.length == 0)	return;
		teacher.validationEngine('hide');	// 隐藏VE的tip，不然会错位

		var isTeacherRequired = teacher.is('.required');
		var val = $(this).val();

		// 清空教授组下拉框，如果不是必填的，塞一个空的选项进去
		teacher.html('');
		if(!isTeacherRequired) teacher.prepend(emptyOption.clone());
		//病区选择了空值，则让教授组选择第一个选项(空)，并手动触发select事件，返回
		if(!val){
			teacher.selectedIndex = 0;
			$.uniform.update(teacher);
			teacher.trigger("change");
		}else{
			$.get($.appCtx+ "/data-manage/teacher/all/"+val,function(data) {
				var initIndex = 0;	// 初始要选中哪个选项
				if(data){
					var initVal = teacher.attr("init-value");
					$(data).each(function(i,e){
						teacher.append($('<option value="'+e.id+'">'+e.name+'</option>'))
						if(initVal != undefined && initVal == e.id)
							initIndex = i+(isTeacherRequired?0:1);//非必填的科室选择框要多一个空选择项
					});
				}
				teacher.find('option').eq(initIndex).attr('selected',true);
				$.uniform.update(teacher);
				teacher.removeAttr('init-value').trigger("change");
			});
		}
	});

	// select初始状态或者手动设置selectedIndex不会触发change事件。手动触发的顺序自底向上
	$("select.select-team").trigger('change');
	$("select.select-dept").trigger('change');
	$("select.select-ss").trigger('change');

	//uniform - styler for checkbox, radio and file input
	$('select[rel="uniform"],input:checkbox, input:radio, input:file').not('[data-no-uniform="true"],#uniform-is-ajax').uniform();

	//chosen - improves select
	$('[data-rel="chosen"],[rel="chosen"]').chosen();

	//tabs
	$('#myTab a:first').tab('show');
	$('#myTab a').click(function (e) {
	  e.preventDefault();
	  $(this).tab('show');
	});

	//makes elements soratble, elements that sort need to have id attribute to save the result
	$('.sortable').sortable({
		revert:true,
		cancel:'.btn,.box-content,.nav-header',
		update:function(event,ui){
			//line below gives the ids of elements, you can make ajax call here to save it to the database
			//console.log($(this).sortable('toArray'));
		}
	});

	//slider
	$('.slider').slider({range:true,values:[10,65]});

	//tooltip
	$('[rel="tooltip"],[data-rel="tooltip"],[data-toggle="tooltip"]').tooltip();

	//auto grow textarea
	//$('textarea.autogrow').autogrow();

	//popover
	$('[rel="popover"],[data-rel="popover"],[data-toggle="popover"]').popover();

	//file manager
	var elf = $('.file-manager').elfinder({
		url : 'misc/elfinder-connector/connector.php'  // connector URL (REQUIRED)
	}).elfinder('instance');

	//iOS / iPhone style toggle switch
	$('.iphone-toggle').iphoneStyle();

	//star rating
	$('.raty').raty({
		score : 4 //default stars
	});

	//uploadify - multiple uploads
	/*$('#file_upload').uploadify({
		'swf'      : 'misc/uploadify.swf',
		'uploader' : 'misc/uploadify.php'
		// Put your options here
	});*/

	//gallery controlls container animation
	$('ul.gallery li').hover(function(){
		$('img',this).fadeToggle(1000);
		$(this).find('.gallery-controls').remove();
		$(this).append('<div class="well gallery-controls">'+
							'<p><a href="#" class="gallery-edit btn"><i class="icon-edit"></i></a> <a href="#" class="gallery-delete btn"><i class="icon-remove"></i></a></p>'+
						'</div>');
		$(this).find('.gallery-controls').stop().animate({'margin-top':'-1'},400,'easeInQuint');
	},function(){
		$('img',this).fadeToggle(1000);
		$(this).find('.gallery-controls').stop().animate({'margin-top':'-30'},200,'easeInQuint',function(){
				$(this).remove();
		});
	});


	//gallery image controls example
	//gallery delete
	$('.thumbnails').on('click','.gallery-delete',function(e){
		e.preventDefault();
		//get image id
		//alert($(this).parents('.thumbnail').attr('id'));
		$(this).parents('.thumbnail').fadeOut();
	});
	//gallery edit
	$('.thumbnails').on('click','.gallery-edit',function(e){
		e.preventDefault();
		//get image id
		//alert($(this).parents('.thumbnail').attr('id'));
	});

	//gallery colorbox
	//$('.thumbnail a').colorbox({rel:'thumbnail a', transition:"elastic", maxWidth:"95%", maxHeight:"95%"});

	//gallery fullscreen
	$('#toggle-fullscreen').button().click(function () {
		var button = $(this), root = document.documentElement;
		if (!button.hasClass('active')) {
			$('#thumbnails').addClass('modal-fullscreen');
			if (root.webkitRequestFullScreen) {
				root.webkitRequestFullScreen(
					window.Element.ALLOW_KEYBOARD_INPUT
				);
			} else if (root.mozRequestFullScreen) {
				root.mozRequestFullScreen();
			}
		} else {
			$('#thumbnails').removeClass('modal-fullscreen');
			(document.webkitCancelFullScreen ||
				document.mozCancelFullScreen ||
				$.noop).apply(document);
		}
	});

	//tour
	if($('.tour').length && typeof(tour)=='undefined')
	{
		var tour = new Tour();
		tour.addStep({
			element: ".span10:first", /* html element next to which the step popover should be shown */
			placement: "top",
			title: "Custom Tour", /* title of the popover */
			content: "You can create tour like this. Click Next." /* content of the popover */
		});
		tour.addStep({
			element: ".theme-container",
			placement: "left",
			title: "Themes",
			content: "You change your theme from here."
		});
		tour.addStep({
			element: "ul.main-menu a:first",
			title: "Dashboard",
			content: "This is your dashboard from here you will find highlights."
		});
		tour.addStep({
			element: "#for-is-ajax",
			title: "Ajax",
			content: "You can change if pages load with Ajax or not."
		});
		tour.addStep({
			element: ".top-nav a:first",
			placement: "bottom",
			title: "Visit Site",
			content: "Visit your front end from here."
		});

		tour.restart();
	}

	//datatable
	$('.datatable').dataTable({
			"sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span12'i><'span12 center'p>>",
			"sPaginationType": "bootstrap",
			"oLanguage": {
			"sLengthMenu": "_MENU_ records per page"
			}
		} );
	$('.btn-close').live('click',function(e){
		e.preventDefault();
		e.stopPropagation();
		$(this).parent().parent().parent().fadeOut(function(){$(this).parent().remove();});
	});
	$('.btn-minimize').live('click',function(e){
		e.preventDefault();
		var $target = $(this).parent().parent().next('.box-content');
		$('i',$(this)).toggleClass('chevron-up').toggleClass('chevron-down');
		$target.slideToggle();
	});
	$('.btn-setting').click(function(e){
		e.preventDefault();
		$('#myModal').modal('show');
	});




	//initialize the external events for calender

	$('#external-events div.external-event').each(function() {

		// it doesn't need to have a start or end
		var eventObject = {
			title: $.trim($(this).text()) // use the element's text as the event title
		};

		// store the Event Object in the DOM element so we can get to it later
		$(this).data('eventObject', eventObject);

		// make the event draggable using jQuery UI
		$(this).draggable({
			zIndex: 999,
			revert: true,      // will cause the event to go back to its
			revertDuration: 0  //  original position after the drag
		});

	});


	//initialize the calendar
	$('#calendar').fullCalendar({
		header: {
			left: 'prev,next today',
			center: 'title',
			right: 'month,agendaWeek,agendaDay'
		},
		editable: true,
		droppable: true, // this allows things to be dropped onto the calendar !!!
		drop: function(date, allDay) { // this function is called when something is dropped

			// retrieve the dropped element's stored Event Object
			var originalEventObject = $(this).data('eventObject');

			// we need to copy it, so that multiple events don't have a reference to the same object
			var copiedEventObject = $.extend({}, originalEventObject);

			// assign it the date that was reported
			copiedEventObject.start = date;
			copiedEventObject.allDay = allDay;

			// render the event on the calendar
			// the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
			$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);

			// is the "remove after drop" checkbox checked?
			if ($('#drop-remove').is(':checked')) {
				// if so, remove the element from the "Draggable Events" list
				$(this).remove();
			}

		}
	});


	//chart with points
	if($("#sincos").length)
	{
		var sin = [], cos = [];

		for (var i = 0; i < 14; i += 0.5) {
			sin.push([i, Math.sin(i)/i]);
			cos.push([i, Math.cos(i)]);
		}

		var plot = $.plot($("#sincos"),
			   [ { data: sin, label: "sin(x)/x"}, { data: cos, label: "cos(x)" } ], {
				   series: {
					   lines: { show: true  },
					   points: { show: true }
				   },
				   grid: { hoverable: true, clickable: true, backgroundColor: { colors: ["#fff", "#eee"] } },
				   yaxis: { min: -1.2, max: 1.2 },
				   colors: ["#539F2E", "#3C67A5"]
				 });

		function showTooltip(x, y, contents) {
			$('<div id="tooltip">' + contents + '</div>').css( {
				position: 'absolute',
				display: 'none',
				top: y + 5,
				left: x + 5,
				border: '1px solid #fdd',
				padding: '2px',
				'background-color': '#dfeffc',
				opacity: 0.80
			}).appendTo("body").fadeIn(200);
		}

		var previousPoint = null;
		$("#sincos").bind("plothover", function (event, pos, item) {
			$("#x").text(pos.x.toFixed(2));
			$("#y").text(pos.y.toFixed(2));

				if (item) {
					if (previousPoint != item.dataIndex) {
						previousPoint = item.dataIndex;

						$("#tooltip").remove();
						var x = item.datapoint[0].toFixed(2),
							y = item.datapoint[1].toFixed(2);

						showTooltip(item.pageX, item.pageY,
									item.series.label + " of " + x + " = " + y);
					}
				}
				else {
					$("#tooltip").remove();
					previousPoint = null;
				}
		});



		$("#sincos").bind("plotclick", function (event, pos, item) {
			if (item) {
				$("#clickdata").text("You clicked point " + item.dataIndex + " in " + item.series.label + ".");
				plot.highlight(item.series, item.datapoint);
			}
		});
	}

	//flot chart
	if($("#flotchart").length)
	{
		var d1 = [];
		for (var i = 0; i < Math.PI * 2; i += 0.25)
			d1.push([i, Math.sin(i)]);

		var d2 = [];
		for (var i = 0; i < Math.PI * 2; i += 0.25)
			d2.push([i, Math.cos(i)]);

		var d3 = [];
		for (var i = 0; i < Math.PI * 2; i += 0.1)
			d3.push([i, Math.tan(i)]);

		$.plot($("#flotchart"), [
			{ label: "sin(x)",  data: d1},
			{ label: "cos(x)",  data: d2},
			{ label: "tan(x)",  data: d3}
		], {
			series: {
				lines: { show: true },
				points: { show: true }
			},
			xaxis: {
				ticks: [0, [Math.PI/2, "\u03c0/2"], [Math.PI, "\u03c0"], [Math.PI * 3/2, "3\u03c0/2"], [Math.PI * 2, "2\u03c0"]]
			},
			yaxis: {
				ticks: 10,
				min: -2,
				max: 2
			},
			grid: {
				backgroundColor: { colors: ["#fff", "#eee"] }
			}
		});
	}

	//stack chart
	if($("#stackchart").length)
	{
		var d1 = [];
		for (var i = 0; i <= 10; i += 1)
		d1.push([i, parseInt(Math.random() * 30)]);

		var d2 = [];
		for (var i = 0; i <= 10; i += 1)
			d2.push([i, parseInt(Math.random() * 30)]);

		var d3 = [];
		for (var i = 0; i <= 10; i += 1)
			d3.push([i, parseInt(Math.random() * 30)]);

		var stack = 0, bars = true, lines = false, steps = false;

		function plotWithOptions() {
			$.plot($("#stackchart"), [ d1, d2, d3 ], {
				series: {
					stack: stack,
					lines: { show: lines, fill: true, steps: steps },
					bars: { show: bars, barWidth: 0.6 }
				}
			});
		}

		plotWithOptions();

		$(".stackControls input").click(function (e) {
			e.preventDefault();
			stack = $(this).val() == "With stacking" ? true : null;
			plotWithOptions();
		});
		$(".graphControls input").click(function (e) {
			e.preventDefault();
			bars = $(this).val().indexOf("Bars") != -1;
			lines = $(this).val().indexOf("Lines") != -1;
			steps = $(this).val().indexOf("steps") != -1;
			plotWithOptions();
		});
	}

	//pie chart
	var data = [
	{ label: "Internet Explorer",  data: 12},
	{ label: "Mobile",  data: 27},
	{ label: "Safari",  data: 85},
	{ label: "Opera",  data: 64},
	{ label: "Firefox",  data: 90},
	{ label: "Chrome",  data: 112}
	];

	if($("#piechart").length)
	{
		$.plot($("#piechart"), data,
		{
			series: {
					pie: {
							show: true
					}
			},
			grid: {
					hoverable: true,
					clickable: true
			},
			legend: {
				show: false
			}
		});

		function pieHover(event, pos, obj)
		{
			if (!obj)
					return;
			percent = parseFloat(obj.series.percent).toFixed(2);
			$("#hover").html('<span style="font-weight: bold; color: '+obj.series.color+'">'+obj.series.label+' ('+percent+'%)</span>');
		}
		$("#piechart").bind("plothover", pieHover);
	}

	//donut chart
	if($("#donutchart").length)
	{
		$.plot($("#donutchart"), data,
		{
				series: {
						pie: {
								innerRadius: 0.5,
								show: true
						}
				},
				legend: {
					show: false
				}
		});
	}




	 // we use an inline data source in the example, usually data would
	// be fetched from a server
	var data = [], totalPoints = 300;
	function getRandomData() {
		if (data.length > 0)
			data = data.slice(1);

		// do a random walk
		while (data.length < totalPoints) {
			var prev = data.length > 0 ? data[data.length - 1] : 50;
			var y = prev + Math.random() * 10 - 5;
			if (y < 0)
				y = 0;
			if (y > 100)
				y = 100;
			data.push(y);
		}

		// zip the generated y values with the x values
		var res = [];
		for (var i = 0; i < data.length; ++i)
			res.push([i, data[i]])
		return res;
	}

	// setup control widget
	var updateInterval = 30;
	$("#updateInterval").val(updateInterval).change(function () {
		var v = $(this).val();
		if (v && !isNaN(+v)) {
			updateInterval = +v;
			if (updateInterval < 1)
				updateInterval = 1;
			if (updateInterval > 2000)
				updateInterval = 2000;
			$(this).val("" + updateInterval);
		}
	});

	//realtime chart
	if($("#realtimechart").length)
	{
		var options = {
			series: { shadowSize: 1 }, // drawing is faster without shadows
			yaxis: { min: 0, max: 100 },
			xaxis: { show: false }
		};
		var plot = $.plot($("#realtimechart"), [ getRandomData() ], options);
		function update() {
			plot.setData([ getRandomData() ]);
			// since the axes don't change, we don't need to call plot.setupGrid()
			plot.draw();

			setTimeout(update, updateInterval);
		}

		update();
	}
}


//additional functions for data table
$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings )
{
	return {
		"iStart":         oSettings._iDisplayStart,
		"iEnd":           oSettings.fnDisplayEnd(),
		"iLength":        oSettings._iDisplayLength,
		"iTotal":         oSettings.fnRecordsTotal(),
		"iFilteredTotal": oSettings.fnRecordsDisplay(),
		"iPage":          Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ),
		"iTotalPages":    Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength )
	};
}
$.extend( $.fn.dataTableExt.oPagination, {
	"bootstrap": {
		"fnInit": function( oSettings, nPaging, fnDraw ) {
			var oLang = oSettings.oLanguage.oPaginate;
			var fnClickHandler = function ( e ) {
				e.preventDefault();
				if ( oSettings.oApi._fnPageChange(oSettings, e.data.action) ) {
					fnDraw( oSettings );
				}
			};

			$(nPaging).addClass('pagination').append(
				'<ul>'+
					'<li class="prev disabled"><a href="#">&larr; '+oLang.sPrevious+'</a></li>'+
					'<li class="next disabled"><a href="#">'+oLang.sNext+' &rarr; </a></li>'+
				'</ul>'
			);
			var els = $('a', nPaging);
			$(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler );
			$(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler );
		},

		"fnUpdate": function ( oSettings, fnDraw ) {
			var iListLength = 5;
			var oPaging = oSettings.oInstance.fnPagingInfo();
			var an = oSettings.aanFeatures.p;
			var i, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);

			if ( oPaging.iTotalPages < iListLength) {
				iStart = 1;
				iEnd = oPaging.iTotalPages;
			}
			else if ( oPaging.iPage <= iHalf ) {
				iStart = 1;
				iEnd = iListLength;
			} else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) {
				iStart = oPaging.iTotalPages - iListLength + 1;
				iEnd = oPaging.iTotalPages;
			} else {
				iStart = oPaging.iPage - iHalf + 1;
				iEnd = iStart + iListLength - 1;
			}

			for ( i=0, iLen=an.length ; i<iLen ; i++ ) {
				// remove the middle elements
				$('li:gt(0)', an[i]).filter(':not(:last)').remove();

				// add the new list items and their event handlers
				for ( j=iStart ; j<=iEnd ; j++ ) {
					sClass = (j==oPaging.iPage+1) ? 'class="active"' : '';
					$('<li '+sClass+'><a href="#">'+j+'</a></li>')
						.insertBefore( $('li:last', an[i])[0] )
						.bind('click', function (e) {
							e.preventDefault();
							oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
							fnDraw( oSettings );
						} );
				}

				// add / remove disabled classes from the static elements
				if ( oPaging.iPage === 0 ) {
					$('li:first', an[i]).addClass('disabled');
				} else {
					$('li:first', an[i]).removeClass('disabled');
				}

				if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) {
					$('li:last', an[i]).addClass('disabled');
				} else {
					$('li:last', an[i]).removeClass('disabled');
				}
			}
		}
	}
});
